#include "libyuv/native-lib.h"


JNIEXPORT jbyteArray nativeI420ToRGB24(JNIEnv *env, jclass type, jbyteArray src_,
                                       jint width, jint height) {
    jbyte *src = env->GetByteArrayElements(src_, NULL);


    //    int I420ToRGB24(const uint8* src_y, int src_stride_y,
//                    const uint8* src_u, int src_stride_u,
//                    const uint8* src_v, int src_stride_v,
//                    uint8* dst_frame, int dst_stride_frame,
//                    int width, int height);

    uint8_t *src_y = reinterpret_cast<uint8_t *>(src);
    uint8_t *src_u = reinterpret_cast<uint8_t *>(src + width * height);
    uint8_t *src_v = reinterpret_cast<uint8_t *>(src + (width * height + width * height / 4));

    size_t length = width * height * 3;
    uint8_t *dst_frame = static_cast<uint8_t *>(malloc(length));

    int ret = libyuv::I420ToARGB(src_y, width, src_u, width >> 1, src_v,
                                 width >> 1, dst_frame, width * 3, width, height);
    LOGE("********8ret = %d", ret);

    if (src) {
        env->ReleaseByteArrayElements(src_, src, 0);
    }


    jbyteArray jbyteArray1 = env->NewByteArray(length);
    env->SetByteArrayRegion(jbyteArray1, 0, length, reinterpret_cast<const jbyte *>(dst_frame));
    free(dst_frame);
    dst_frame = NULL;
    return jbyteArray1;

}


jbyteArray
nativeCrop(JNIEnv *env, jobject thiz, jbyteArray array, jint width, jint height, jint left,
           jint top, jint d_width, jint d_height) {
    LOGI("nativeCrop");
    jbyte *src = env->GetByteArrayElements(array, NULL);


    //    int I420ToRGB24(const uint8* src_y, int src_stride_y,
//                    const uint8* src_u, int src_stride_u,
//                    const uint8* src_v, int src_stride_v,
//                    uint8* dst_frame, int dst_stride_frame,
//                    int width, int height);

    uint8_t *src_y = reinterpret_cast<uint8_t *>(src);
    uint8_t *src_u = reinterpret_cast<uint8_t *>(src + width * height);
    uint8_t *src_v = reinterpret_cast<uint8_t *>(src + (width * height + width * height / 4));

    size_t length = width * height * 4;
    uint8_t *dst_frame = static_cast<uint8_t *>(malloc(length));

    int ret = I420ToRGBA(src_y, width, src_u, width >> 1, src_v,
                                 width >> 1, dst_frame, width * 4, width, height);
    LOGE("********8ret = %d", ret);

    jbyteArray jbyteArray1 = NULL;
    if(!ret){
        //success
        uint8_t *dst_argb = static_cast<uint8_t *>(malloc(d_width * d_height * 4));
//        int r = ARGBScaleClip(dst_frame,width * 3,width,height,dst_argb,d_width * 3,d_width,d_height,left,top,d_width - left,d_height-top,kFilterNone);
        int r = ConvertToARGB(dst_frame,length,dst_argb,d_width * 4,left,top,width,height,d_height,d_height,kRotate0,FOURCC_RGBA);
        LOGW("ConvertToARGB = %d",r);
        if(!r){
            jbyteArray1 = env->NewByteArray(d_width * d_height * 4);
            env->SetByteArrayRegion(jbyteArray1, 0, d_width * d_height * 4, reinterpret_cast<const jbyte *>(dst_argb));
        }
        free(dst_argb);
        dst_argb = NULL;


    }
    if (src) {
        env->ReleaseByteArrayElements(array, src, 0);
    }

    free(dst_frame);
    dst_frame = NULL;
    return jbyteArray1;
}


//**********************************************************************
//
//**********************************************************************

static JNINativeMethod methods[] = {
        {"nativeI420ToRGB24", "([BII)[B", (void *) nativeI420ToRGB24},
        {"nativeCrop", "([BIIIIII)[B", (void *) nativeCrop},

};

jint registerNativeMethods(JNIEnv *env, const char *class_name, JNINativeMethod *methods,
                           int num_methods) {
    int result = 0;

    jclass clazz = env->FindClass(class_name);
    if (LIKELY(clazz)) {
        int result = env->RegisterNatives(clazz, methods, num_methods);
        if (UNLIKELY(result < 0)) {
            LOGE("registerNativeMethods failed(class=%s)", class_name);
        }
    } else {
        LOGE("registerNativeMethods: class'%s' not found", class_name);
    }
    return result;
}


int register_method(JNIEnv *env) {
    LOGV("register_libstream_jni:");
    if (registerNativeMethods(env,
                              "com/media/yuvplayer/utils/YuvUtils",
                              methods, NUM_ARRAY_ELEMENTS(methods)) < 0) {
        return -1;
    }
    return 0;
}
